﻿using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Markup;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Threading;
using System.Xml;
using System.Xml.Linq;
using ActionLogic;
using BehaviorModel;
using BehaviorModel.Block;
using CommandLogic;
using CommandLogic.Command;
using CommandLogic.Data;
using Microsoft.Win32;
using QSDesigner.Windows;
using QSDesigner.Windows.Interfaces;

namespace QSDesigner
{
    public partial class DesignerCanvas
    {
        public static RoutedCommand Group = new RoutedCommand();
        public static RoutedCommand Ungroup = new RoutedCommand();
        public static RoutedCommand BringForward = new RoutedCommand();
        public static RoutedCommand BringToFront = new RoutedCommand();
        public static RoutedCommand SendBackward = new RoutedCommand();
        public static RoutedCommand SendToBack = new RoutedCommand();
        public static RoutedCommand AlignTop = new RoutedCommand();
        public static RoutedCommand AlignVerticalCenters = new RoutedCommand();
        public static RoutedCommand AlignBottom = new RoutedCommand();
        public static RoutedCommand AlignLeft = new RoutedCommand();
        public static RoutedCommand AlignHorizontalCenters = new RoutedCommand();
        public static RoutedCommand AlignRight = new RoutedCommand();
        public static RoutedCommand DistributeHorizontal = new RoutedCommand();
        public static RoutedCommand DistributeVertical = new RoutedCommand();
        public static RoutedCommand SelectAll = new RoutedCommand();

        public static RoutedCommand Start = new RoutedCommand();
        public static RoutedCommand Pause = new RoutedCommand();
        public static RoutedCommand Stop = new RoutedCommand();

        public static RoutedCommand ShowProperties = new RoutedCommand();

        public static RoutedCommand ShowAvgQueueLengthByChannels = new RoutedCommand();
        public static RoutedCommand ShowСhannelsTimeAllocation = new RoutedCommand();
        public static RoutedCommand ShowRejectProbabilityHistogramData = new RoutedCommand();

        //public static RoutedCommand ShowHistogram = new RoutedCommand();

        public static RoutedCommand GridOn = new RoutedCommand();

        public DesignerCanvas()
        {
            this.CommandBindings.Add(new CommandBinding(ApplicationCommands.New, New_Executed));
            this.CommandBindings.Add(new CommandBinding(ApplicationCommands.Open, Open_Executed, Open_Enabled));
            this.CommandBindings.Add(new CommandBinding(ApplicationCommands.Save, Save_Executed, Save_Enabled));
            this.CommandBindings.Add(new CommandBinding(ApplicationCommands.Print, Print_Executed));
            this.CommandBindings.Add(new CommandBinding(ApplicationCommands.Cut, Cut_Executed, Cut_Enabled));
            this.CommandBindings.Add(new CommandBinding(ApplicationCommands.Copy, Copy_Executed, Copy_Enabled));
            this.CommandBindings.Add(new CommandBinding(ApplicationCommands.Paste, Paste_Executed, Paste_Enabled));
            this.CommandBindings.Add(new CommandBinding(ApplicationCommands.Delete, Delete_Executed, Delete_Enabled));
            this.CommandBindings.Add(new CommandBinding(DesignerCanvas.Group, Group_Executed, Group_Enabled));
            this.CommandBindings.Add(new CommandBinding(DesignerCanvas.Ungroup, Ungroup_Executed, Ungroup_Enabled));
            this.CommandBindings.Add(new CommandBinding(DesignerCanvas.BringForward, BringForward_Executed, Order_Enabled));
            this.CommandBindings.Add(new CommandBinding(DesignerCanvas.BringToFront, BringToFront_Executed, Order_Enabled));
            this.CommandBindings.Add(new CommandBinding(DesignerCanvas.SendBackward, SendBackward_Executed, Order_Enabled));
            this.CommandBindings.Add(new CommandBinding(DesignerCanvas.SendToBack, SendToBack_Executed, Order_Enabled));
            this.CommandBindings.Add(new CommandBinding(DesignerCanvas.AlignTop, AlignTop_Executed, Align_Enabled));
            this.CommandBindings.Add(new CommandBinding(DesignerCanvas.AlignVerticalCenters, AlignVerticalCenters_Executed, Align_Enabled));
            this.CommandBindings.Add(new CommandBinding(DesignerCanvas.AlignBottom, AlignBottom_Executed, Align_Enabled));
            this.CommandBindings.Add(new CommandBinding(DesignerCanvas.AlignLeft, AlignLeft_Executed, Align_Enabled));
            this.CommandBindings.Add(new CommandBinding(DesignerCanvas.AlignHorizontalCenters, AlignHorizontalCenters_Executed, Align_Enabled));
            this.CommandBindings.Add(new CommandBinding(DesignerCanvas.AlignRight, AlignRight_Executed, Align_Enabled));
            this.CommandBindings.Add(new CommandBinding(DesignerCanvas.DistributeHorizontal, DistributeHorizontal_Executed, Distribute_Enabled));
            this.CommandBindings.Add(new CommandBinding(DesignerCanvas.DistributeVertical, DistributeVertical_Executed, Distribute_Enabled));
            this.CommandBindings.Add(new CommandBinding(DesignerCanvas.SelectAll, SelectAll_Executed));

            this.CommandBindings.Add(new CommandBinding(DesignerCanvas.Start, Start_Executed, Start_Enabled));
            this.CommandBindings.Add(new CommandBinding(DesignerCanvas.Pause, Pause_Executed, Pause_Enabled));
            this.CommandBindings.Add(new CommandBinding(DesignerCanvas.Stop, Stop_Executed, Stop_Enabled));

            this.CommandBindings.Add(new CommandBinding(DesignerCanvas.ShowProperties, ShowProperties_Executed, ShowProperties_Enabled));
            //this.CommandBindings.Add(new CommandBinding(DesignerCanvas.ShowHistogram, ShowHistogram_Executed, ShowHistogram_Enabled));

            //this.CommandBindings.Add(new CommandBinding(DesignerCanvas.GridOn, GridOn_Executed, GridOn_Enabled));

            this.CommandBindings.Add(new CommandBinding(DesignerCanvas.ShowAvgQueueLengthByChannels,
                ShowAvgQueueLengthByChannels_Executed, ShowAvgQueueLengthByChannels_Enabled));

            this.CommandBindings.Add(new CommandBinding(DesignerCanvas.ShowСhannelsTimeAllocation,
                ShowСhannelsTimeAllocation_Executed, ShowСhannelsTimeAllocation_Enabled));

            this.CommandBindings.Add(new CommandBinding(DesignerCanvas.ShowRejectProbabilityHistogramData,
                ShowRejectProbabilityHistogramData_Executed, ShowRejectProbabilityHistogramData_Enabled));

            SelectAll.InputGestures.Add(new KeyGesture(Key.A, ModifierKeys.Control));

            this.AllowDrop = true;

            Clipboard.Clear();
        }

        #region New Command

        private void New_Executed(object sender, ExecutedRoutedEventArgs e)
        {
            var deleteAllBlocksCommand = QsmCommandFactory.GetCommand(QsmCommand.DeleteAllBlocks);
            deleteAllBlocksCommand.Execute(null);

            this.Children.Clear();
            this.SelectionService.ClearSelection();
        }

        #endregion

        #region Open Command

        private void Open_Executed(object sender, ExecutedRoutedEventArgs e)
        {
            XElement root = LoadSerializedDataFromFile();

            if (root == null)
                return;

            var deleteAllBlocksCommand = QsmCommandFactory.GetCommand(QsmCommand.DeleteAllBlocks);
            deleteAllBlocksCommand.Execute(null);

            this.Children.Clear();
            this.SelectionService.ClearSelection();

            IEnumerable<XElement> itemsXML = root.Elements("DesignerItems").Elements("DesignerItem");
            foreach (XElement itemXML in itemsXML)
            {
                Guid id = new Guid(itemXML.Element("ID").Value);
                DesignerItem item = DeserializeDesignerItem(itemXML, id, 0, 0);
                this.Children.Add(item);
                SetConnectorDecoratorTemplate(item);
            }

            this.InvalidateVisual();

            IEnumerable<XElement> connectionsXML = root.Elements("Connections").Elements("Connection");
            foreach (XElement connectionXML in connectionsXML)
            {
                Guid sourceID = new Guid(connectionXML.Element("SourceID").Value);
                Guid sinkID = new Guid(connectionXML.Element("SinkID").Value);

                String sourceConnectorName = connectionXML.Element("SourceConnectorName").Value;
                String sinkConnectorName = connectionXML.Element("SinkConnectorName").Value;

                Connector sourceConnector = GetConnector(sourceID, sourceConnectorName);
                Connector sinkConnector = GetConnector(sinkID, sinkConnectorName);

                //Create new item
                var connectBlocksCommand = QsmCommandFactory.GetCommand(QsmCommand.ConnectBlocks);
                var commandData = new SenderReceiverData
                {
                    SenderBlock = (ISenderBlock)sourceConnector.ParentDesignerItem.Block,
                    RecieverBlock = (IReceiverBlock)sinkConnector.ParentDesignerItem.Block
                };
                connectBlocksCommand.Execute(commandData);

                Connection connection = new Connection(sourceConnector, sinkConnector);
                Canvas.SetZIndex(connection, Int32.Parse(connectionXML.Element("zIndex").Value));
                this.Children.Add(connection);
            }

            //Надо обновить, иначе упадает
            InitializeSystemStatisticsContentControl();
        }

        private void Open_Enabled(object sender, CanExecuteRoutedEventArgs e)
        {
            e.CanExecute = true;
        }

        #endregion

        #region Save Command

        private void Save_Executed(object sender, ExecutedRoutedEventArgs e)
        {
            IEnumerable<DesignerItem> designerItems = this.Children.OfType<DesignerItem>();
            IEnumerable<Connection> connections = this.Children.OfType<Connection>();

            XElement designerItemsXML = SerializeDesignerItems(designerItems);
            XElement connectionsXML = SerializeConnections(connections);

            XElement root = new XElement("Root");
            root.Add(designerItemsXML);
            root.Add(connectionsXML);

            SaveFile(root);
        }

        private void Save_Enabled(object sender, CanExecuteRoutedEventArgs e)
        {
            e.CanExecute = true;
        }

        #endregion

        #region Print Command

        private void Print_Executed(object sender, ExecutedRoutedEventArgs e)
        {
            SelectionService.ClearSelection();

            PrintDialog printDialog = new PrintDialog();

            if (true == printDialog.ShowDialog())
            {
                printDialog.PrintVisual(this, "WPF Diagram");
            }
        }

        #endregion

        #region Copy Command

        private void Copy_Executed(object sender, ExecutedRoutedEventArgs e)
        {
            CopyCurrentSelection();
        }

        private void Copy_Enabled(object sender, CanExecuteRoutedEventArgs e)
        {
            e.CanExecute = SelectionService.CurrentSelection.Count() > 0;
            //e.CanExecute = false;
        }

        #endregion

        #region Paste Command

        private void Paste_Executed(object sender, ExecutedRoutedEventArgs e)
        {
            XElement root = LoadSerializedDataFromClipBoard();

            if (root == null)
                return;

            // create DesignerItems
            Dictionary<Guid, Guid> mappingOldToNewIDs = new Dictionary<Guid, Guid>();
            List<ISelectable> newItems = new List<ISelectable>();
            IEnumerable<XElement> itemsXML = root.Elements("DesignerItems").Elements("DesignerItem");

            double offsetX = Double.Parse(root.Attribute("OffsetX").Value, CultureInfo.InvariantCulture);
            double offsetY = Double.Parse(root.Attribute("OffsetY").Value, CultureInfo.InvariantCulture);

            foreach (XElement itemXML in itemsXML)
            {
                Guid oldID = new Guid(itemXML.Element("ID").Value);
                Guid newID = Guid.NewGuid();
                mappingOldToNewIDs.Add(oldID, newID);
                DesignerItem item = DeserializeDesignerItem(itemXML, newID, offsetX, offsetY);
                this.Children.Add(item);
                SetConnectorDecoratorTemplate(item);
                newItems.Add(item);
            }

            // update group hierarchy
            SelectionService.ClearSelection();
            foreach (DesignerItem el in newItems)
            {
                if (el.ParentID != Guid.Empty)
                    el.ParentID = mappingOldToNewIDs[el.ParentID];
            }


            foreach (DesignerItem item in newItems)
            {
                if (item.ParentID == Guid.Empty)
                {
                    SelectionService.AddToSelection(item);
                }
            }

            // create Connections
            IEnumerable<XElement> connectionsXML = root.Elements("Connections").Elements("Connection");
            foreach (XElement connectionXML in connectionsXML)
            {
                Guid oldSourceID = new Guid(connectionXML.Element("SourceID").Value);
                Guid oldSinkID = new Guid(connectionXML.Element("SinkID").Value);

                if (mappingOldToNewIDs.ContainsKey(oldSourceID) && mappingOldToNewIDs.ContainsKey(oldSinkID))
                {
                    Guid newSourceID = mappingOldToNewIDs[oldSourceID];
                    Guid newSinkID = mappingOldToNewIDs[oldSinkID];

                    String sourceConnectorName = connectionXML.Element("SourceConnectorName").Value;
                    String sinkConnectorName = connectionXML.Element("SinkConnectorName").Value;

                    Connector sourceConnector = GetConnector(newSourceID, sourceConnectorName);
                    Connector sinkConnector = GetConnector(newSinkID, sinkConnectorName);

                    Connection connection = new Connection(sourceConnector, sinkConnector);
                    Canvas.SetZIndex(connection, Int32.Parse(connectionXML.Element("zIndex").Value));
                    this.Children.Add(connection);

                    SelectionService.AddToSelection(connection);
                }
            }

            DesignerCanvas.BringToFront.Execute(null, this);

            // update paste offset
            root.Attribute("OffsetX").Value = (offsetX + 10).ToString();
            root.Attribute("OffsetY").Value = (offsetY + 10).ToString();
            Clipboard.Clear();
            Clipboard.SetData(DataFormats.Xaml, root);
        }

        private void Paste_Enabled(object sender, CanExecuteRoutedEventArgs e)
        {
            e.CanExecute = Clipboard.ContainsData(DataFormats.Xaml);
            //e.CanExecute = false;
        }

        #endregion


        #region Delete Command

        private void Delete_Executed(object sender, ExecutedRoutedEventArgs e)
        {
            DeleteCurrentSelection();
        }

        private void Delete_Enabled(object sender, CanExecuteRoutedEventArgs e)
        {
            e.CanExecute = this.SelectionService.CurrentSelection.Count() > 0;
        }

        #endregion

        #region Cut Command

        private void Cut_Executed(object sender, ExecutedRoutedEventArgs e)
        {
            CopyCurrentSelection();
            DeleteCurrentSelection();
        }

        private void Cut_Enabled(object sender, CanExecuteRoutedEventArgs e)
        {
            //e.CanExecute = this.SelectionService.CurrentSelection.Count() > 0;
            e.CanExecute = false;
        }


        #endregion

        #region Group Command

        private void Group_Executed(object sender, ExecutedRoutedEventArgs e)
        {
            var items = from item in this.SelectionService.CurrentSelection.OfType<DesignerItem>()
                        where item.ParentID == Guid.Empty
                        select item;

            Rect rect = GetBoundingRectangle(items);

            DesignerItem groupItem = new DesignerItem();
            groupItem.IsGroup = true;
            groupItem.Width = rect.Width;
            groupItem.Height = rect.Height;
            Canvas.SetLeft(groupItem, rect.Left);
            Canvas.SetTop(groupItem, rect.Top);
            Canvas groupCanvas = new Canvas();
            groupItem.Content = groupCanvas;
            Canvas.SetZIndex(groupItem, this.Children.Count);
            this.Children.Add(groupItem);

            foreach (DesignerItem item in items)
                item.ParentID = groupItem.ID;

            this.SelectionService.SelectItem(groupItem);
        }

        private void Group_Enabled(object sender, CanExecuteRoutedEventArgs e)
        {
            int count = (from item in SelectionService.CurrentSelection.OfType<DesignerItem>()
                         where item.ParentID == Guid.Empty
                         select item).Count();

            e.CanExecute = count > 1;
        }

        #endregion

        #region Ungroup Command

        private void Ungroup_Executed(object sender, ExecutedRoutedEventArgs e)
        {
            var groups = (from item in SelectionService.CurrentSelection.OfType<DesignerItem>()
                          where item.IsGroup && item.ParentID == Guid.Empty
                          select item).ToArray();

            foreach (DesignerItem groupRoot in groups)
            {
                var children = from child in SelectionService.CurrentSelection.OfType<DesignerItem>()
                               where child.ParentID == groupRoot.ID
                               select child;

                foreach (DesignerItem child in children)
                    child.ParentID = Guid.Empty;

                this.SelectionService.RemoveFromSelection(groupRoot);
                this.Children.Remove(groupRoot);
                UpdateZIndex();
            }
        }

        private void Ungroup_Enabled(object sender, CanExecuteRoutedEventArgs e)
        {
            var groupedItem = from item in SelectionService.CurrentSelection.OfType<DesignerItem>()
                              where item.ParentID != Guid.Empty
                              select item;


            e.CanExecute = groupedItem.Count() > 0;
        }

        #endregion

        #region BringForward Command

        private void BringForward_Executed(object sender, ExecutedRoutedEventArgs e)
        {
            List<UIElement> ordered = (from item in SelectionService.CurrentSelection
                                       orderby Canvas.GetZIndex(item as UIElement) descending
                                       select item as UIElement).ToList();

            int count = this.Children.Count;

            for (int i = 0; i < ordered.Count; i++)
            {
                int currentIndex = Canvas.GetZIndex(ordered[i]);
                int newIndex = Math.Min(count - 1 - i, currentIndex + 1);
                if (currentIndex != newIndex)
                {
                    Canvas.SetZIndex(ordered[i], newIndex);
                    IEnumerable<UIElement> it = this.Children.OfType<UIElement>().Where(item => Canvas.GetZIndex(item) == newIndex);

                    foreach (UIElement elm in it)
                    {
                        if (elm != ordered[i])
                        {
                            Canvas.SetZIndex(elm, currentIndex);
                            break;
                        }
                    }
                }
            }
        }

        private void Order_Enabled(object sender, CanExecuteRoutedEventArgs e)
        {
            //e.CanExecute = SelectionService.CurrentSelection.Count() > 0;
            e.CanExecute = true;
        }

        #endregion

        #region BringToFront Command

        private void BringToFront_Executed(object sender, ExecutedRoutedEventArgs e)
        {
            List<UIElement> selectionSorted = (from item in SelectionService.CurrentSelection
                                               orderby Canvas.GetZIndex(item as UIElement) ascending
                                               select item as UIElement).ToList();

            List<UIElement> childrenSorted = (from UIElement item in this.Children
                                              orderby Canvas.GetZIndex(item as UIElement) ascending
                                              select item as UIElement).ToList();

            int i = 0;
            int j = 0;
            foreach (UIElement item in childrenSorted)
            {
                if (selectionSorted.Contains(item))
                {
                    int idx = Canvas.GetZIndex(item);
                    Canvas.SetZIndex(item, childrenSorted.Count - selectionSorted.Count + j++);
                }
                else
                {
                    Canvas.SetZIndex(item, i++);
                }
            }
        }

        #endregion

        #region SendBackward Command

        private void SendBackward_Executed(object sender, ExecutedRoutedEventArgs e)
        {
            List<UIElement> ordered = (from item in SelectionService.CurrentSelection
                                       orderby Canvas.GetZIndex(item as UIElement) ascending
                                       select item as UIElement).ToList();

            int count = this.Children.Count;

            for (int i = 0; i < ordered.Count; i++)
            {
                int currentIndex = Canvas.GetZIndex(ordered[i]);
                int newIndex = Math.Max(i, currentIndex - 1);
                if (currentIndex != newIndex)
                {
                    Canvas.SetZIndex(ordered[i], newIndex);
                    IEnumerable<UIElement> it = this.Children.OfType<UIElement>().Where(item => Canvas.GetZIndex(item) == newIndex);

                    foreach (UIElement elm in it)
                    {
                        if (elm != ordered[i])
                        {
                            Canvas.SetZIndex(elm, currentIndex);
                            break;
                        }
                    }
                }
            }
        }

        #endregion

        #region SendToBack Command

        private void SendToBack_Executed(object sender, ExecutedRoutedEventArgs e)
        {
            List<UIElement> selectionSorted = (from item in SelectionService.CurrentSelection
                                               orderby Canvas.GetZIndex(item as UIElement) ascending
                                               select item as UIElement).ToList();

            List<UIElement> childrenSorted = (from UIElement item in this.Children
                                              orderby Canvas.GetZIndex(item as UIElement) ascending
                                              select item as UIElement).ToList();
            int i = 0;
            int j = 0;
            foreach (UIElement item in childrenSorted)
            {
                if (selectionSorted.Contains(item))
                {
                    int idx = Canvas.GetZIndex(item);
                    Canvas.SetZIndex(item, j++);

                }
                else
                {
                    Canvas.SetZIndex(item, selectionSorted.Count + i++);
                }
            }
        }

        #endregion

        #region AlignTop Command

        private void AlignTop_Executed(object sender, ExecutedRoutedEventArgs e)
        {
            var selectedItems = from item in SelectionService.CurrentSelection.OfType<DesignerItem>()
                                where item.ParentID == Guid.Empty
                                select item;

            if (selectedItems.Count() > 1)
            {
                double top = Canvas.GetTop(selectedItems.First());

                foreach (DesignerItem item in selectedItems)
                {
                    double delta = top - Canvas.GetTop(item);
                    foreach (DesignerItem di in SelectionService.GetGroupMembers(item))
                    {
                        Canvas.SetTop(di, Canvas.GetTop(di) + delta);
                    }
                }
            }
        }

        private void Align_Enabled(object sender, CanExecuteRoutedEventArgs e)
        {
            //var groupedItem = from item in SelectionService.CurrentSelection.OfType<DesignerItem>()
            //                  where item.ParentID == Guid.Empty
            //                  select item;


            //e.CanExecute = groupedItem.Count() > 1;
            e.CanExecute = true;
        }

        #endregion

        #region AlignVerticalCenters Command

        private void AlignVerticalCenters_Executed(object sender, ExecutedRoutedEventArgs e)
        {
            var selectedItems = from item in SelectionService.CurrentSelection.OfType<DesignerItem>()
                                where item.ParentID == Guid.Empty
                                select item;

            if (selectedItems.Count() > 1)
            {
                double bottom = Canvas.GetTop(selectedItems.First()) + selectedItems.First().Height / 2;

                foreach (DesignerItem item in selectedItems)
                {
                    double delta = bottom - (Canvas.GetTop(item) + item.Height / 2);
                    foreach (DesignerItem di in SelectionService.GetGroupMembers(item))
                    {
                        Canvas.SetTop(di, Canvas.GetTop(di) + delta);
                    }
                }
            }
        }

        #endregion

        #region AlignBottom Command

        private void AlignBottom_Executed(object sender, ExecutedRoutedEventArgs e)
        {
            var selectedItems = from item in SelectionService.CurrentSelection.OfType<DesignerItem>()
                                where item.ParentID == Guid.Empty
                                select item;

            if (selectedItems.Count() > 1)
            {
                double bottom = Canvas.GetTop(selectedItems.First()) + selectedItems.First().Height;

                foreach (DesignerItem item in selectedItems)
                {
                    double delta = bottom - (Canvas.GetTop(item) + item.Height);
                    foreach (DesignerItem di in SelectionService.GetGroupMembers(item))
                    {
                        Canvas.SetTop(di, Canvas.GetTop(di) + delta);
                    }
                }
            }
        }

        #endregion

        #region AlignLeft Command

        private void AlignLeft_Executed(object sender, ExecutedRoutedEventArgs e)
        {
            var selectedItems = from item in SelectionService.CurrentSelection.OfType<DesignerItem>()
                                where item.ParentID == Guid.Empty
                                select item;

            if (selectedItems.Count() > 1)
            {
                double left = Canvas.GetLeft(selectedItems.First());

                foreach (DesignerItem item in selectedItems)
                {
                    double delta = left - Canvas.GetLeft(item);
                    foreach (DesignerItem di in SelectionService.GetGroupMembers(item))
                    {
                        Canvas.SetLeft(di, Canvas.GetLeft(di) + delta);
                    }
                }
            }
        }

        #endregion

        #region AlignHorizontalCenters Command

        private void AlignHorizontalCenters_Executed(object sender, ExecutedRoutedEventArgs e)
        {
            var selectedItems = from item in SelectionService.CurrentSelection.OfType<DesignerItem>()
                                where item.ParentID == Guid.Empty
                                select item;

            if (selectedItems.Count() > 1)
            {
                double center = Canvas.GetLeft(selectedItems.First()) + selectedItems.First().Width / 2;

                foreach (DesignerItem item in selectedItems)
                {
                    double delta = center - (Canvas.GetLeft(item) + item.Width / 2);
                    foreach (DesignerItem di in SelectionService.GetGroupMembers(item))
                    {
                        Canvas.SetLeft(di, Canvas.GetLeft(di) + delta);
                    }
                }
            }
        }

        #endregion

        #region AlignRight Command

        private void AlignRight_Executed(object sender, ExecutedRoutedEventArgs e)
        {
            var selectedItems = from item in SelectionService.CurrentSelection.OfType<DesignerItem>()
                                where item.ParentID == Guid.Empty
                                select item;

            if (selectedItems.Count() > 1)
            {
                double right = Canvas.GetLeft(selectedItems.First()) + selectedItems.First().Width;

                foreach (DesignerItem item in selectedItems)
                {
                    double delta = right - (Canvas.GetLeft(item) + item.Width);
                    foreach (DesignerItem di in SelectionService.GetGroupMembers(item))
                    {
                        Canvas.SetLeft(di, Canvas.GetLeft(di) + delta);
                    }
                }
            }
        }

        #endregion

        #region DistributeHorizontal Command

        private void DistributeHorizontal_Executed(object sender, ExecutedRoutedEventArgs e)
        {
            var selectedItems = from item in SelectionService.CurrentSelection.OfType<DesignerItem>()
                                where item.ParentID == Guid.Empty
                                let itemLeft = Canvas.GetLeft(item)
                                orderby itemLeft
                                select item;

            if (selectedItems.Count() > 1)
            {
                double left = Double.MaxValue;
                double right = Double.MinValue;
                double sumWidth = 0;
                foreach (DesignerItem item in selectedItems)
                {
                    left = Math.Min(left, Canvas.GetLeft(item));
                    right = Math.Max(right, Canvas.GetLeft(item) + item.Width);
                    sumWidth += item.Width;
                }

                double distance = Math.Max(0, (right - left - sumWidth) / (selectedItems.Count() - 1));
                double offset = Canvas.GetLeft(selectedItems.First());

                foreach (DesignerItem item in selectedItems)
                {
                    double delta = offset - Canvas.GetLeft(item);
                    foreach (DesignerItem di in SelectionService.GetGroupMembers(item))
                    {
                        Canvas.SetLeft(di, Canvas.GetLeft(di) + delta);
                    }
                    offset = offset + item.Width + distance;
                }
            }
        }

        private void Distribute_Enabled(object sender, CanExecuteRoutedEventArgs e)
        {
            //var groupedItem = from item in SelectionService.CurrentSelection.OfType<DesignerItem>()
            //                  where item.ParentID == Guid.Empty
            //                  select item;


            //e.CanExecute = groupedItem.Count() > 1;
            e.CanExecute = true;
        }

        #endregion

        #region DistributeVertical Command

        private void DistributeVertical_Executed(object sender, ExecutedRoutedEventArgs e)
        {
            var selectedItems = from item in SelectionService.CurrentSelection.OfType<DesignerItem>()
                                where item.ParentID == Guid.Empty
                                let itemTop = Canvas.GetTop(item)
                                orderby itemTop
                                select item;

            if (selectedItems.Count() > 1)
            {
                double top = Double.MaxValue;
                double bottom = Double.MinValue;
                double sumHeight = 0;
                foreach (DesignerItem item in selectedItems)
                {
                    top = Math.Min(top, Canvas.GetTop(item));
                    bottom = Math.Max(bottom, Canvas.GetTop(item) + item.Height);
                    sumHeight += item.Height;
                }

                double distance = Math.Max(0, (bottom - top - sumHeight) / (selectedItems.Count() - 1));
                double offset = Canvas.GetTop(selectedItems.First());

                foreach (DesignerItem item in selectedItems)
                {
                    double delta = offset - Canvas.GetTop(item);
                    foreach (DesignerItem di in SelectionService.GetGroupMembers(item))
                    {
                        Canvas.SetTop(di, Canvas.GetTop(di) + delta);
                    }
                    offset = offset + item.Height + distance;
                }
            }
        }

        #endregion

        #region SelectAll Command

        private void SelectAll_Executed(object sender, ExecutedRoutedEventArgs e)
        {
            SelectionService.SelectAll();
        }

        #endregion


        #region Start Command

        private readonly Func<bool> _isStart = () => ActionExecutor.GetInstance().ActionExecutorState == ActionExecutorState.Start;

        private void Start_Executed(object sender, ExecutedRoutedEventArgs e)
        {
            //Start statistics
            var startCommand = QsmCommandFactory.GetCommand(QsmCommand.Start);
            startCommand.Execute(null);

            //Если пауза и есть открытые графики
            if (_isPause() && AppMonitor.GraphicsWindows.Count > 0)
            {
                var designerItems = this.Children.OfType<DesignerItem>().ToList().Where(x => x.Block.Type == BlockType.ServiceChannel).ToList();

                //Если кол-во каналов в окне отличается от текущего, то обновляем модель.
                if (AppMonitor.LastItemsCount != designerItems.Count)
                {
                    var avgQueueLengthByChannelsWindow = ((IAvgQueueLengthByChannelsWindow)AppMonitor.GraphicsWindows.Find(win => win is IAvgQueueLengthByChannelsWindow));
                    if (avgQueueLengthByChannelsWindow != null)
                    {
                        avgQueueLengthByChannelsWindow.UpdateModel();
                    }
                }

                AppMonitor.GraphicsWindows.ForEach(win => ((IUpdatableWindow)win).StartFetchData());
            }

            RunDispatcher();
        }

        private void Start_Enabled(object sender, CanExecuteRoutedEventArgs e)
        {
            e.CanExecute = !_isStart();
        }

        #endregion

        #region Pause Command

        private readonly Func<bool> _isPause = () => ActionExecutor.GetInstance().ActionExecutorState == ActionExecutorState.Pause;

        private void Pause_Executed(object sender, ExecutedRoutedEventArgs e)
        {
            //Pause statistics
            var startCommand = QsmCommandFactory.GetCommand(QsmCommand.Pause);
            startCommand.Execute(null);
            //this.IsEnabled = true;
            _stopFetchData();
        }

        private void Pause_Enabled(object sender, CanExecuteRoutedEventArgs e)
        {
            e.CanExecute = _isStart();
        }

        #endregion

        #region Stop Command

        private readonly Func<bool> _isStop = () => ActionExecutor.GetInstance().ActionExecutorState == ActionExecutorState.Stop;

        private readonly Action _stopFetchDataAndCloseGraphicsWindows = () =>
                                                                  {
                                                                      AppMonitor.DispatcherTimer.Stop();

                                                                      if (AppMonitor.GraphicsWindows.Count == 0) return;

                                                                      AppMonitor.GraphicsWindows.ForEach(win => ((IUpdatableWindow)win).StopFetchData());

                                                                      while (AppMonitor.GraphicsWindows.Count != 0)
                                                                      {
                                                                          AppMonitor.GraphicsWindows.First().Close();
                                                                      }
                                                                  };
        private readonly Action _stopFetchData = () =>
                                {
                                    AppMonitor.DispatcherTimer.Stop();
                                    if (AppMonitor.GraphicsWindows.Count > 0)
                                    {
                                        AppMonitor.GraphicsWindows.ForEach(win => ((IUpdatableWindow)win).StopFetchData());
                                    }
                                };

        private void Stop_Executed(object sender, ExecutedRoutedEventArgs e)
        {
            //Pause statistics
            var startCommand = QsmCommandFactory.GetCommand(QsmCommand.Stop);
            startCommand.Execute(null);
            //this.IsEnabled = true;
            _stopFetchDataAndCloseGraphicsWindows();
        }

        private void Stop_Enabled(object sender, CanExecuteRoutedEventArgs e)
        {
            e.CanExecute = _isStart() || _isPause();
        }

        #endregion

        #region ShowProperties

        private void ShowProperties_Executed(object sender, ExecutedRoutedEventArgs e)
        {

            var toolboxImage = sender as DesignerCanvas;

            if (toolboxImage != null)
            {
                var selectionService = toolboxImage.selectionService;

                var designerItem = selectionService.CurrentSelection[0] as DesignerItem;

                var window = new PropertiesWindow {Item = designerItem};
                window.Show();
                
                //WindowManager.LaunchWindowNewThread<PropertiesWindow>(designerItem/*, (o, args) => ((PropertiesWindow) o).Init()*/);

            }

            e.Handled = true;
        }

        private void ShowProperties_Enabled(object sender, CanExecuteRoutedEventArgs e)
        {
            e.CanExecute = true;
        }

        #endregion

        /*#region ShowHistogram

        private void ShowHistogram_Executed(object sender, ExecutedRoutedEventArgs e)
        {
            var toolboxImage = sender as DesignerCanvas;

            if (toolboxImage != null)
            {
                var selectionService = toolboxImage.selectionService;

                var designerItem = selectionService.CurrentSelection[0] as DesignerItem;

                //TODO There need to check for checkers correctly

                var checkers = new List<string> {"CHECKER_UNIFORM", "CHECKER_EXPONENTIAL", "CHECKER_GAUSSIAN"};

                if (designerItem != null && checkers.Contains(designerItem.Block.Type))
                {
                    WindowManager.LaunchWindowNewThread<CheckerWindow>(designerItem);
                }
            }

            e.Handled = true;
        }

        private void ShowHistogram_Enabled(object sender, CanExecuteRoutedEventArgs e)
        {
            e.CanExecute = true;
        }

        #endregion*/


        #region GridOn

        private void GridOn_Executed(object sender, ExecutedRoutedEventArgs e)
        {
            /*var contextMenu = (ContextMenu)FindResource("DesignerCanvasContextMenu");

            foreach (MenuItem menuItem in contextMenu.Items)
            {
                if (menuItem.Name == "DesignerCanvasGrid")
                {
                    if (!menuItem.)
                    {
                        ImageBrush myBrush = new ImageBrush();
                        Image image = new Image
                        {
                            Source = new BitmapImage(
                                new Uri(
                                    "pack://application:,,,/QSDesigner;component/Resources/Images/gridIcon.png"))
                        };
                        myBrush.ImageSource = image.Source;
                        myBrush.Viewport = new Rect(0, 0, 16, 16);
                        myBrush.TileMode = TileMode.Tile;
                        myBrush.ViewportUnits = BrushMappingMode.Absolute;

                        this.Background = myBrush;
                    }
                    else
                    {
                        this.Background = Brushes.White;
                    }
                }
            }*/

            ImageBrush myBrush = new ImageBrush();
            Image image = new Image
            {
                Source = new BitmapImage(
                    new Uri(
                        "pack://application:,,,/QSDesigner;component/Resources/Images/gridIcon.png"))
            };
            myBrush.ImageSource = image.Source;
            myBrush.Viewport = new Rect(0, 0, 16, 16);
            myBrush.TileMode = TileMode.Tile;
            myBrush.ViewportUnits = BrushMappingMode.Absolute;

            this.Background = myBrush;

            e.Handled = true;
        }

        private void GridOn_Enabled(object sender, CanExecuteRoutedEventArgs e)
        {
            e.CanExecute = true;
        }


        #endregion

        #region Graphics

        #region ShowAvgQueueLengthByChannels

        private void ShowAvgQueueLengthByChannels_Executed(object sender, ExecutedRoutedEventArgs e)
        {
            if (_isStop()) return;

            CreateAndShowGraphic(() => new AvgQueueLengthByChannelsWindow(this));
        }

        private void ShowAvgQueueLengthByChannels_Enabled(object sender, CanExecuteRoutedEventArgs e)
        {
            e.CanExecute =  !_isStop() && !AppMonitor.GraphicsWindows.Exists(window => window is IAvgQueueLengthByChannelsWindow);
        }

        #endregion

        #region ShowСhannelsTimeAllocation

        private void ShowСhannelsTimeAllocation_Executed(object sender, ExecutedRoutedEventArgs e)
        {
            if (_isStop()) return;

            CreateAndShowGraphic(() => new СhannelsTimeAllocationWindow());
        }

        private void ShowСhannelsTimeAllocation_Enabled(object sender, CanExecuteRoutedEventArgs e)
        {
            e.CanExecute = !_isStop() && !AppMonitor.GraphicsWindows.Exists(window => window is IСhannelsTimeAllocationWindow);
        }

        #endregion

        #region ShowRejectProbabilityHistogramData

        private void ShowRejectProbabilityHistogramData_Executed(object sender, ExecutedRoutedEventArgs e)
        {
            if (_isStop()) return;

            CreateAndShowGraphic(() => new RejectProbabilityHistogramDataWindow());
        }

        private void ShowRejectProbabilityHistogramData_Enabled(object sender, CanExecuteRoutedEventArgs e)
        {
            e.CanExecute = !_isStop() && !AppMonitor.GraphicsWindows.Exists(window => window is IRejectProbabilityHistogramDataWindow);
        }

        #endregion

        private void CreateAndShowGraphic(Func<Window> constructor)
        {
            //Запонимаем первонач. кол-во эл-ов
            AppMonitor.LastItemsCount = this.Children.OfType<DesignerItem>().Count(x => x.Block.Type == BlockType.ServiceChannel);
            
            var win = constructor();
            win.Show();

            if (_isPause())
            {
                ((IUpdatableWindow)win).UpdateChart();
            }
            else
            {
                ((IUpdatableWindow)win).StartFetchData();
            }

            win.Closed += (s, ev) => AppMonitor.GraphicsWindows.Remove((Window)s);
            AppMonitor.GraphicsWindows.Add(win);
        }

        #endregion

        #region Helper Methods

        private XElement LoadSerializedDataFromFile()
        {
            OpenFileDialog openFile = new OpenFileDialog();
            openFile.Filter = "Designer Files (*.xml)|*.xml|All Files (*.*)|*.*";

            if (openFile.ShowDialog() == true)
            {
                try
                {
                    return XElement.Load(openFile.FileName);
                }
                catch (Exception e)
                {
                    MessageBox.Show(e.StackTrace, e.Message, MessageBoxButton.OK, MessageBoxImage.Error);
                }
            }

            return null;
        }

        void SaveFile(XElement xElement)
        {
            SaveFileDialog saveFile = new SaveFileDialog();
            saveFile.Filter = "Files (*.xml)|*.xml|All Files (*.*)|*.*";
            if (saveFile.ShowDialog() == true)
            {
                try
                {
                    xElement.Save(saveFile.FileName);
                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.StackTrace, ex.Message, MessageBoxButton.OK, MessageBoxImage.Error);
                }
            }
        }

        private XElement LoadSerializedDataFromClipBoard()
        {
            if (Clipboard.ContainsData(DataFormats.Xaml))
            {
                String clipboardData = Clipboard.GetData(DataFormats.Xaml) as String;

                if (String.IsNullOrEmpty(clipboardData))
                    return null;
                try
                {
                    return XElement.Load(new StringReader(clipboardData));
                }
                catch (Exception e)
                {
                    MessageBox.Show(e.StackTrace, e.Message, MessageBoxButton.OK, MessageBoxImage.Error);
                }
            }

            return null;
        }

        private XElement SerializeDesignerItems(IEnumerable<DesignerItem> designerItems)
        {
            XElement serializedItems = new XElement("DesignerItems",
                                       from item in designerItems
                                       let contentXaml = XamlWriter.Save(((DesignerItem)item).Content)
                                       select new XElement("DesignerItem",
                                                  new XElement("Left", Canvas.GetLeft(item)),
                                                  new XElement("Top", Canvas.GetTop(item)),
                                                  new XElement("Width", item.Width),
                                                  new XElement("Height", item.Height),
                                                  new XElement("ID", item.ID),
                                                  BehaviorModel.XmlSerializer.XmlSerializerFactory.GetInstance().Create(item.Block.Type).ToXElement(item.Block),
                                                  new XElement("BlockType", item.Block.Type),
                                                  new XElement("BlockName", item.BlockName),
                                                  new XElement("UniqueColor", item.UniqueColor),
                                                  new XElement("zIndex", Canvas.GetZIndex(item)),
                                                  new XElement("IsGroup", item.IsGroup),
                                                  new XElement("ParentID", item.ParentID),
                                                  new XElement("Content", contentXaml)
                                              )
                                   );

            return serializedItems;
        }

        private XElement SerializeConnections(IEnumerable<Connection> connections)
        {
            var serializedConnections = new XElement("Connections",
                           from connection in connections
                           select new XElement("Connection",
                                      new XElement("SourceID", connection.Source.ParentDesignerItem.ID),
                                      new XElement("SinkID", connection.Sink.ParentDesignerItem.ID),
                                      new XElement("SourceConnectorName", connection.Source.Name),
                                      new XElement("SinkConnectorName", connection.Sink.Name),
                                      new XElement("SourceArrowSymbol", connection.SourceArrowSymbol),
                                      new XElement("SinkArrowSymbol", connection.SinkArrowSymbol),
                                      new XElement("zIndex", Canvas.GetZIndex(connection))
                                     )
                                  );

            return serializedConnections;
        }

        private static DesignerItem DeserializeDesignerItem(XElement itemXML, Guid id, double OffsetX, double OffsetY)
        {
            DesignerItem item = new DesignerItem(id);

            item.Width = Double.Parse(itemXML.Element("Width").Value, CultureInfo.InvariantCulture);
            item.Height = Double.Parse(itemXML.Element("Height").Value, CultureInfo.InvariantCulture);
            item.ParentID = new Guid(itemXML.Element("ParentID").Value);

            var blockType = itemXML.Element("BlockType").Value;
            CreateBlockBasedOn(item, BehaviorModel.XmlSerializer.XmlSerializerFactory.GetInstance().Create((BlockType)Enum.Parse(typeof(BlockType), blockType)).FromXElement(itemXML), (BlockType)Enum.Parse(typeof(BlockType), blockType));

            item.BlockName = itemXML.Element("BlockName").Value;

            item.UniqueColor = new BrushConverter().ConvertFromString(itemXML.Element("UniqueColor").Value) as Brush;

            item.IsGroup = Boolean.Parse(itemXML.Element("IsGroup").Value);
            Canvas.SetLeft(item, Double.Parse(itemXML.Element("Left").Value, CultureInfo.InvariantCulture) + OffsetX);
            Canvas.SetTop(item, Double.Parse(itemXML.Element("Top").Value, CultureInfo.InvariantCulture) + OffsetY);
            Canvas.SetZIndex(item, Int32.Parse(itemXML.Element("zIndex").Value));
            Object content = XamlReader.Load(XmlReader.Create(new StringReader(itemXML.Element("Content").Value)));
            item.Content = content;
            return item;
        }

        private void CopyCurrentSelection()
        {
            IEnumerable<DesignerItem> selectedDesignerItems =
                this.SelectionService.CurrentSelection.OfType<DesignerItem>();

            List<Connection> selectedConnections =
                this.SelectionService.CurrentSelection.OfType<Connection>().ToList();

            foreach (Connection connection in this.Children.OfType<Connection>())
            {
                if (!selectedConnections.Contains(connection))
                {
                    DesignerItem sourceItem = (from item in selectedDesignerItems
                                               where item.ID == connection.Source.ParentDesignerItem.ID
                                               select item).FirstOrDefault();

                    DesignerItem sinkItem = (from item in selectedDesignerItems
                                             where item.ID == connection.Sink.ParentDesignerItem.ID
                                             select item).FirstOrDefault();

                    if (sourceItem != null &&
                        sinkItem != null &&
                        BelongToSameGroup(sourceItem, sinkItem))
                    {
                        selectedConnections.Add(connection);
                    }
                }
            }

            XElement designerItemsXML = SerializeDesignerItems(selectedDesignerItems);
            XElement connectionsXML = SerializeConnections(selectedConnections);

            XElement root = new XElement("Root");
            root.Add(designerItemsXML);
            root.Add(connectionsXML);

            root.Add(new XAttribute("OffsetX", 10));
            root.Add(new XAttribute("OffsetY", 10));

            Clipboard.Clear();
            Clipboard.SetData(DataFormats.Xaml, root);
        }

        private void DeleteCurrentSelection()
        {
            var disconnectBlocksCommand = QsmCommandFactory.GetCommand(QsmCommand.DisconnectBlocks);
            var deleteBlockCommand = QsmCommandFactory.GetCommand(QsmCommand.DeleteBlock);

            foreach (Connection connection in SelectionService.CurrentSelection.OfType<Connection>())
            {
                this.Children.Remove(connection);
                //Disconnect blocks
                var commandData = new SenderReceiverData
                {
                    SenderBlock = (ISenderBlock)connection.Source.ParentDesignerItem.Block,
                    RecieverBlock = (IReceiverBlock)connection.Sink.ParentDesignerItem.Block
                };
                disconnectBlocksCommand.Execute(commandData);
            }

            foreach (DesignerItem item in SelectionService.CurrentSelection.OfType<DesignerItem>())
            {
                Control cd = item.Template.FindName("PART_ConnectorDecorator", item) as Control;

                List<Connector> connectors = new List<Connector>();
                GetConnectors(cd, connectors);

                foreach (Connector connector in connectors)
                {
                    foreach (Connection con in connector.Connections)
                    {
                        this.Children.Remove(con);
                        //Disconnect blocks
                        /*var commandData = new SenderRecieverData
                        {
                            SenderBlock = (ISenderBlock)con.Source.ParentDesignerItem.Block,
                            RecieverBlock = (IReceiverBlock)con.Sink.ParentDesignerItem.Block
                        };
                        disconnectBlocksCommand.Execute(commandData); */
                    }
                }
                this.Children.Remove(item);

                //Delete item
                var blockData = new BlockData { Block = item.Block };
                deleteBlockCommand.Execute(blockData);
            }

            SelectionService.ClearSelection();
            UpdateZIndex();
        }

        private void UpdateZIndex()
        {
            List<UIElement> ordered = (from UIElement item in this.Children
                                       orderby Canvas.GetZIndex(item as UIElement)
                                       select item as UIElement).ToList();

            for (int i = 0; i < ordered.Count; i++)
            {
                Canvas.SetZIndex(ordered[i], i);
            }
        }

        private static Rect GetBoundingRectangle(IEnumerable<DesignerItem> items)
        {
            double x1 = Double.MaxValue;
            double y1 = Double.MaxValue;
            double x2 = Double.MinValue;
            double y2 = Double.MinValue;

            foreach (DesignerItem item in items)
            {
                x1 = Math.Min(Canvas.GetLeft(item), x1);
                y1 = Math.Min(Canvas.GetTop(item), y1);

                x2 = Math.Max(Canvas.GetLeft(item) + item.Width, x2);
                y2 = Math.Max(Canvas.GetTop(item) + item.Height, y2);
            }

            return new Rect(new Point(x1, y1), new Point(x2, y2));
        }

        private void GetConnectors(DependencyObject parent, List<Connector> connectors)
        {
            int childrenCount = VisualTreeHelper.GetChildrenCount(parent);
            for (int i = 0; i < childrenCount; i++)
            {
                DependencyObject child = VisualTreeHelper.GetChild(parent, i);
                if (child is Connector)
                {
                    connectors.Add(child as Connector);
                }
                else
                    GetConnectors(child, connectors);
            }
        }

        private Connector GetConnector(Guid itemID, String connectorName)
        {
            DesignerItem designerItem = (from item in this.Children.OfType<DesignerItem>()
                                         where item.ID == itemID
                                         select item).FirstOrDefault();

            Control connectorDecorator = designerItem.Template.FindName("PART_ConnectorDecorator", designerItem) as Control;
            connectorDecorator.ApplyTemplate();

            return connectorDecorator.Template.FindName(connectorName, connectorDecorator) as Connector;
        }

        private bool BelongToSameGroup(IGroupable item1, IGroupable item2)
        {
            IGroupable root1 = SelectionService.GetGroupRoot(item1);
            IGroupable root2 = SelectionService.GetGroupRoot(item2);

            return (root1.ID == root2.ID);
        }

        #region Additions

        private void RunDispatcher()
        {
            AppMonitor.DispatcherTimer.Tick += (s, a) =>
                                                    {
                                                        Action action = !AppMonitor.IsWholeSystemStatisticsShowing
                                                                            ? (Action)UpdateBlockStatistic
                                                                            : UpdateSystemStatistic;

                                                        Dispatcher.Invoke(action);
                                                    };

            AppMonitor.DispatcherTimer.Start();

        }

        public void InitializeBlockStatisticsContentControl(DesignerItem item)
        {

            var contentControl = (ContentControl)FindName("StatisticProperties");

            if (contentControl != null)
            {
                contentControl.Content = AppMonitor.BlockStatisticDictionary["BlockStatisticProperties"];

                if (_isStart() || _isPause())
                {
                    var selectedBlock = (DesignerItem) SelectionService.CurrentSelection[0];

                    UpdateContentControlProperties(contentControl, selectedBlock.Block);
                }

                AppMonitor.IsWholeSystemStatisticsShowing = false;
            }

        }

        public void InitializeSystemStatisticsContentControl()
        {
            var contentControl = (ContentControl)FindName("StatisticProperties");

            if (contentControl != null)
            {
                contentControl.Content = AppMonitor.SystemStatisticDictionary["SystemStatisticProperties"];

                if (_isStart() || _isPause())
                {
                    var updateStatisticCommand = new UpdateStatisticCommand();
                    updateStatisticCommand.Execute(null);

                    var groupBox = contentControl.Content as GroupBox;
                    if (groupBox != null)
                    {
                        groupBox.DataContext = null;
                        groupBox.DataContext = StatisticController.GetInstance().Statistic;
                    }
                }

                AppMonitor.IsWholeSystemStatisticsShowing = true;
            }

        }

        public void UpdateBlockStatistic()
        {
            if (SelectionService.CurrentSelection.Count != 0 && (_isStart() || (_isPause())))
            {
                var updateStatisticCommand = QsmCommandFactory.GetCommand(QsmCommand.UpdateStatistic);
                updateStatisticCommand.Execute(null);
                var selectedBlock = (DesignerItem) SelectionService.CurrentSelection[0];

                var contentControl = (ContentControl) FindName("StatisticProperties");
                if (contentControl != null)
                {
                    UpdateContentControlProperties(contentControl, selectedBlock.Block);
                }
            }
        }

        public void UpdateSystemStatistic()
        {
            if (_isStart() || _isPause())
            {
                var updateStatisticCommand = new UpdateStatisticCommand();
                updateStatisticCommand.Execute(null);

                var contentControl = (ContentControl)FindName("StatisticProperties");
                if (contentControl != null)
                {
                    var groupBox = contentControl.Content as GroupBox;
                    if (groupBox != null)
                    {
                        groupBox.DataContext = null;
                        groupBox.DataContext = StatisticController.GetInstance().Statistic;
                    }
                }
            }
        }

        private void UpdateContentControlProperties(ContentControl contentControl, IBlock selectedBlock)
        {
            var groupBox = contentControl.Content as GroupBox;

            if (groupBox != null)
            {
                groupBox.DataContext = null;
                groupBox.DataContext = selectedBlock.Statistic;

                if (AppMonitor.SelectedBlock == null || selectedBlock.Type != AppMonitor.SelectedBlock.Type)
                {
                    var stackPanel = new StackPanel();

                    foreach (var c in LogicalTreeHelper.GetChildren(groupBox))
                    {
                        if (c is StackPanel)
                        {
                            stackPanel = c as StackPanel;
                            break;
                        }
                    }

                    var count = VisualTreeHelper.GetChildrenCount(stackPanel);
                    var blockType = selectedBlock.Type.ToString();

                    for (int i = 0; i < count; i++)
                    {
                        var childVisual = (Visual)VisualTreeHelper.GetChild(stackPanel, i);
                        if (childVisual is Grid)
                        {
                            var grid = (Grid)childVisual;
                            grid.Visibility = grid.Name == blockType
                                                  ? Visibility.Visible
                                                  : Visibility.Collapsed;
                        }
                    }

                    AppMonitor.SelectedBlock = selectedBlock;
                }

            }
        }


        /*public void ShowBlockStatisticProperties(DesignerItem designerItem)
        {
            var state = ActionExecutor.GetInstance().ActionExecutorState;
            if (state == ActionExecutorState.Start || state == ActionExecutorState.Pause)
            {
                var resourceDictionary = new ResourceDictionary
                {
                    Source =
                        new Uri(
                        "/QSDesigner;component/Resources/Properties/Statistics Properties/BlockStatisticProperties.xaml",
                        UriKind.RelativeOrAbsolute)
                };

                UpdateProperties(designerItem, resourceDictionary, "BlockStatisticProperties");
            }
        }*/

        /* private void UpdateProperties(DesignerItem designerItem, ResourceDictionary resourceDictionary, String propertiesName)
         {
             var contentControl = (ContentControl)FindName("StatisticProperties");

             if (contentControl != null) contentControl.Content = resourceDictionary[propertiesName];

             var currentBlock = StatisticController.GetInstance().Statistic[designerItem.Block.Id];

             UpdateContentControlProperties(contentControl, currentBlock, designerItem.Block.Type.ToString());
         }*/

        /*private void ShowSystemStatisticProperties()
        {

            var state = ActionExecutor.GetInstance().ActionExecutorState;
            if (state == ActionExecutorState.Start || state == ActionExecutorState.Pause)
            {
                var resourceDictionary = new ResourceDictionary
                {
                    Source =
                        new Uri(
                        "/QSDesigner;component/Resources/Properties/Statistics Properties/SystemStatisticProperties.xaml",
                        UriKind.RelativeOrAbsolute)
                };


                var contentControl = (ContentControl)FindName("StatisticProperties");

                if (contentControl != null)
                {
                    contentControl.Content = resourceDictionary["SystemStatisticProperties"];

                    var updateStatisticCommand = new UpdateStatisticCommand();
                    updateStatisticCommand.Execute(null);
                    contentControl.DataContext = StatisticController.GetInstance().Statistic;
                }
            }

        }*/

        #endregion



        //-----------------


        /*public void ShowProperties(DesignerItem designerItem)
        {

            WindowManager.LaunchWindowNewThread<PropertiesWindow>(designerItem);

        }*/

        #endregion

    }

}
